﻿using System;
using RepositoryFramework.Exceptions;
using RepositoryFramework.Validators;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Portal.Logic.Validators;
using Portal.Model;
using Portal.Repository;
using Rhino.Mocks;

namespace Portal.Logic.Services.Tests.Units
{
	[TestClass()]
	public class ContactInfoServiceTests : ServiceBaseTests<ContactInfoService, IContactInfo, IContactInfoValidator, IPortalUnitOfWorkProvider, IPortalUnitOfWork>
	{
		private IContactInfoRepository _repository;

		protected override void InitializeTest()
		{
			base.InitializeTest();
			_repository = Mocks.DynamicMock<IContactInfoRepository>();
			Validator = Mocks.DynamicMock<IContactInfoValidator>();
			SetupResult.For(UnitOfWork.ContactInfoRepository).Return(_repository);
		}

		#region AddOrUpdate

		[TestMethod()]
		public void AddOrUpdate_ContactInfoIsNull_ReturnsNull()
		{
			var user = Mocks.Stub<IUser>();
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.AddOrUpdate(_repository, user, null);

			result.Should().BeNull();
		}

		[TestMethod()]
		[ExpectedException(typeof(ArgumentNullException))]
		public void AddOrUpdate_RepositoryIsNull_ThrowsException()
		{
			var info = Mocks.Stub<IContactInfo>();
			var user = Mocks.Stub<IUser>();
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.AddOrUpdate(null, user, info);
		}

		[TestMethod()]
		[ExpectedException(typeof(ArgumentNullException))]
		public void AddOrUpdate_UserIsNull_ThrowsException()
		{
			var info = Mocks.Stub<IContactInfo>();
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.AddOrUpdate(_repository, null, info);
		}

		[TestMethod()]
		[ExpectedException(typeof(CustomValidationException))]
		public void AddOrUpdate_ContactInfoIsNotValid_ThrowsException()
		{
			var info = Mocks.Stub<IContactInfo>();
			var user = Mocks.Stub<IUser>();
			var validationResult = Mocks.DynamicMock<IValidationResult>();
			SetupResult.For(validationResult.IsValid).Return(false);
			Expect.Call(Validator.Validate(info)).Return(validationResult);
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.AddOrUpdate(_repository, user, info);
		}

		[TestMethod()]
		public void AddOrUpdate_CorrectInput_ReturnsContactInfo()
		{
			var info = Mocks.Stub<IContactInfo>();
			var user = Mocks.Stub<IUser>();
			var validationResult = Mocks.DynamicMock<IValidationResult>();
			SetupResult.For(validationResult.IsValid).Return(true);
			Expect.Call(Validator.Validate(info)).Return(validationResult);
			Expect.Call(_repository.AddOrUpdate(user, info)).Return(info);
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.AddOrUpdate(_repository, user, info);

			result.Should().Be(info);
		}

		#endregion AddOrUpdate

		#region DeleteAllBy

		[TestMethod()]
		[ExpectedException(typeof(ArgumentNullException))]
		public void DeleteAllBy_RepositoryIsNull_ThrowsException()
		{
			var user = Mocks.Stub<IUser>();
			Mocks.ReplayAll();

			var service = GetService();
			service.DeleteAllBy(null, user);
		}

		[TestMethod()]
		public void DeleteAllBy_CorrectInput_Success()
		{
			var user = Mocks.Stub<IUser>();
			Expect.Call(() => _repository.DeleteAllBy(user)).Repeat.Once();
			Mocks.ReplayAll();

			var service = GetService();
			service.DeleteAllBy(_repository, user);

			Mocks.Verify(_repository);
		}

		#endregion DeleteAllBy

		protected override ContactInfoService GetService()
		{
			return new ContactInfoService(Provider, Validator);
		}
	}
}